from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
# 加载 .env 到环境变量
from dotenv import load_dotenv, find_dotenv
from langfuse.decorators import observe, langfuse_context

_ = load_dotenv(find_dotenv())
''' 
 这个实际应用就是根据已有的内容，然后根据用户提出的问题判断是否在改内容之内，如果在就返回true，否则返回false
 每次调用大模型之前，要先判断这个问题是否已经有人提出了，如果有人提出了，则直接返回true，否则加入问题列表

'''

# 需要回答问题的prompt
need_answer = PromptTemplate.from_template(
    """
    *********
    你是AIGC课程的助教，你的工作是从学员的课堂交流中选择出需要老师回答的问题，加以整理以交给老师回答。
     
    课程内容:
    {outlines}
    *********
    学员输入:
    {user_input}
    *********
    如果这是一个需要老师答疑的问题，回复Y，否则回复N。
    只回复Y或N，不要回复其他内容。
    """
)

# 检测提出的问题是否已经有答案了
check_duplicated = PromptTemplate.from_template(
    """
*********
已有提问列表:
[
{question_list}
]
*********
新提问:
{user_input}
*********
已有提问列表是否有和新提问类似的问题? 回复Y或N, Y表示有，N表示没有。
只回复Y或N，不要回复其他内容。
    """
)
# 课程内容
outlines = """
LangChain
模型 I/O 封装
模型的封装
模型的输入输出
PromptTemplate
OutputParser
数据连接封装
文档加载器：Document Loaders
文档处理器
内置RAG：RetrievalQA
记忆封装：Memory
链架构：Chain/LCEL
大模型时代的软件架构：Agent
ReAct
SelfAskWithSearch
LangServe
LangChain.js
"""
# 问题列表
question_list = [
    "LangChain可以商用吗",
    "LangChain开源吗",
]
parser = StrOutputParser()
# 创建 chain
model = ChatOpenAI(temperature=0, model_kwargs={"seed": 42})
need_answer_chain = (
        need_answer
        | model
        | parser
)
# 是否需要回答 chain
is_duplicated_chain = (
        check_duplicated
        | model
        | parser
)


# 主流程
@observe()
def verify_question(
        question: str,
        outlines: str,
        question_list: list,
        user_id: str,
) -> bool:
    langfuse_context.update_current_trace(
        name="AGIClassAssistant",
        user_id=user_id
    )
    # get the langchain handler for the current trace
    langfuse_handler = langfuse_context.get_current_langchain_handler()
    # 判断是否需要回答
    if need_answer_chain.invoke({"outlines": outlines, "user_input": question},
                                config={"callbacks": [langfuse_handler]}) == "Y":
        # 判断问题是否重复
        if is_duplicated_chain.invoke({"question_list": "\n".join(question_list), "user_input": question},
                                      config={"callbacks": [langfuse_handler]}) == "N":
            # 问题不重复，加入到新的问题列表
            question_list.append(question)
            return True
    return False


# 实际调用
ret = verify_question(
    "LangChain支持不懂计算机的人学习吗",
    outlines,
    question_list,
    "bml"
)
print(ret)
